package ai4games_tests.soccer;

import game2dai.Domain;
import game2dai.World;
import game2dai.entities.Artefact;
import game2dai.entities.BaseEntity;
import game2dai.entityshapes.ps.CirclePic;
import game2dai.entityshapes.ps.PicturePS;
import game2dai.maths.Vector2D;
import game2dai.utils.StopWatch;
import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PImage;

public class Pitch extends Artefact implements Constants {

	World world;
	PApplet app;
	PFont font0, font1;

	float length = (float) PITCH_LENGTH;
	float width = (float) PITCH_WIDTH;

	StopWatch sw = new StopWatch();

	Ball ball;

	Team[] teams = new Team[2];
	int[][] teamColors;
	String[] teamNames;
	float[] nameWidths;
	int[] teamScore = new int[2];
	int[] teamColorIdx = {-1, -1};

	boolean showSpots = false;
	
	// Pitch regions for players and region IDs for each team
	Domain[] regions;
	int[][] playerRegionIDs = { 
			{ 1,3,6,5,8,1,4,12,8,14 },		// pitch side 0
			{ 16,12,9,14,11,16,9,3,13,5 }	// pitch side 1
	};

	// Supporting spots on pitch
	Vector2D[][] sspots = new Vector2D[2][30];

	boolean ballInPlay = false;
	boolean playersOffPitch = true;

	public Pitch(PApplet papp, World world, float length, float width){
		super(null, null, length,  width);
		app = papp;
		font0 = app.createFont("Sans Serif", 24);
		font1 = app.createFont("Sans Serif", 18);
		this.world = world;
		
		addFSM();
		createRegions();
		createSupportingSpotPositions();

		teamColors = new int[6][];
		teamColors[0] = new int[] { app.color(255,0,0), app.color(255,200,200), app.color(96,0,0), app.color(128,0,0) };
		teamColors[1] = new int[] { app.color(0,0,255), app.color(200,200,255), app.color(0,0,96), app.color(0,0,128) };
		teamColors[2] = new int[] { app.color(255,0,255), app.color(255,200,255), app.color(96,0,96), app.color(128,0,128) };
		teamColors[3] = new int[] { app.color(255,128,0), app.color(255,192,64), app.color(166,82,0), app.color(238,118,0) };
		teamColors[4] = new int[] { app.color(0,255,255), app.color(200,255,255), app.color(0,96,96), app.color(0,128,128) };
		teamColors[5] = new int[] { app.color(230), app.color(190), app.color(96), app.color(128) };

		teamNames = new String[] {
				"Red Socks", "Blue Bottles", "Purple Hearts", "Orange Pips", "Cyan Eyeds", "Grey Beards"
		};
		nameWidths = new float[teamNames.length];
		app.textFont(font0);
		for(int i = 0; i < teamNames.length; i++)
			nameWidths[i] = app.textWidth(teamNames[i]);

		createBall();
		world.add(ball);

		teams[0] = new Team(app, this, world, 0);
		teams[1] = new Team(app, this, world, 1);

		newTeams();
		
		// Create the renderer for the pitch
		renderer(new PitchRenderer(app, "ai4g/grass.jpg"));

		addFSM();
		FSM().setGlobalState(PitchGlobal.state());
		world.add(this);
	}

	/**
	 * Make sure we have two different teams
	 */
	public void newTeams(){
		int t0 = teamColorIdx[0];
		int t1 = teamColorIdx[1];
		int nt0, nt1;
		do {
			nt0 = (int) app.random(teamColors.length);
		} while(nt0 == t0 || nt0 == t1);
		do {
			nt1 = (int) app.random(teamColors.length);
		} while(nt1 == nt0 || nt1 == t0 || nt1 == t1);
		teamColorIdx[0] = nt0;
		teamColorIdx[1] = nt1;
		teams[0].setTeamColors(teamColors[teamColorIdx[0]]);
		teams[1].setTeamColors(teamColors[teamColorIdx[1]]);
		teamScore[0] = teamScore[1] = 0;
	}

	private void createRegions(){
		regions = new Domain[18];
		double sizex = PITCH_LENGTH/6;
		double sizey = PITCH_WIDTH/3;
		double px, py;
		for(int i = 0; i < regions.length; i++){
			px = (i/3) * sizex;
			py = (i%3) * sizey;
			regions[i] = new Domain(px,py,px+sizex,py+sizey);
		}
	}

	public Domain getRegion(int nbr){
		return regions[nbr];
	}

	public int getRegionID(int side, int playerNo, int teamState){
		int p = (teamState == ATTACKING_STATE) ? 5 : 0;
		return playerRegionIDs[side][playerNo + p];
	}

	private void createSupportingSpotPositions() {
		double deltaX = PITCH_LENGTH * 0.5 * 0.12;
		double deltaY = PITCH_WIDTH * 0.12;
		double startX = PITCH_LENGTH * 0.5 * 0.26;
		double startY = PITCH_WIDTH * 0.20;
		for(int sp = 0; sp < sspots[0].length; sp++){
			int r = sp / 5;
			int c = sp % 5;
			sspots[1][sp] = new Vector2D(startX + c * deltaX, startY + r * deltaY);
			sspots[0][sp] = new Vector2D(PITCH_LENGTH - sspots[1][sp].x, PITCH_WIDTH - sspots[1][sp].y);
		}
	}

	public Team getTeam(int pitch_side){
		return teams[pitch_side];
	}

	public boolean isValidBallPos(Vector2D p){
		double br = ball.colRadius();
		return p.x - br > 0 && p.x + br < PITCH_LENGTH && p.y - br > 0 && p.y + br < PITCH_WIDTH;
	}

	private void createBall(){
		ball = new Ball(this);
		ball.renderer(new CirclePic(app, 2 * BALL_RADIUS, app.color(0), app.color(255), 1.2f));
		ball.Z(-2);
		ball.toCentreSpot(PITCH_LENGTH/2, PITCH_WIDTH/2);
		ball.toCentreSpot(PITCH_LENGTH/2, PITCH_WIDTH/2);
		world.add(ball);
	}

	// Called from Game class
	public void setTeamColors(int team, int col){
		teamColorIdx[team] = col;
		teams[team].setTeamColors(teamColors[col]);
	}

	/**
	 * 
	 * The pitch renderer implemented as an inner class.
	 * @author Peter Lager
	 *
	 */
	public class PitchRenderer extends PicturePS implements Constants {
		PImage grass;
		int lineCol;
		float lineWidth;

		public PitchRenderer(PApplet papp, String imgFilename) {
			super(papp);
			grass = app.loadImage(imgFilename);
			this.lineCol = app.color(255, 255, 255);
			lineWidth = 3;
		}

		@Override
		public void draw(BaseEntity owner, float posX, float posY, float velX,
				float velY, float headX, float headY) {
			app.pushStyle();
			app.pushMatrix();
			app.rectMode(PApplet.CORNER);
			app.ellipseMode(PApplet.CENTER);
			app.image(grass, 0, 0);
			app.noFill();
			app.stroke(lineCol);
			app.strokeWeight(lineWidth);
			app.rect(0,0, PITCH_LENGTH, PITCH_WIDTH);
			app.fill(lineCol);
			app.ellipse(PITCH_LENGTH/2, PITCH_WIDTH/2, 5, 5);
			app.noFill();
			app.ellipse(PITCH_LENGTH/2, PITCH_WIDTH/2, 160, 160);
			// Goals
			app.line(PITCH_LENGTH/2, 0, PITCH_LENGTH/2, PITCH_WIDTH);
			app.rect(0, GOAL_WIDTH, GOAL_DEPTH, GOAL_WIDTH);
			app.rect(PITCH_LENGTH - GOAL_DEPTH, GOAL_WIDTH, 30, GOAL_WIDTH);

			app.fill(teamColors[teamColorIdx[0]][0]);
			app.textFont(font0);
			app.text(teamNames[teamColorIdx[0]], 0, -30);
			app.textFont(font1);
			app.text(teamScore[0], 50, -8);

			app.fill(teamColors[teamColorIdx[1]][0]);
			app.textFont(font0);
			app.text(teamNames[teamColorIdx[1]], (float) (PITCH_LENGTH - nameWidths[teamColorIdx[1]]), -30);
			app.textFont(font1);
			app.text(teamScore[1], (float) (PITCH_LENGTH) - 50 - app.textWidth(""+ teamScore[1]), -8);

			if(showSpots)
				for(Team t : teams)
					t.drawSupportingSpots();

			String clockText;
			if(!playersOffPitch){
				app.noStroke();
				app.fill(255);
				float gtime = (float) sw.getRunTime();
				float d = TIMER_LENGTH  - TIMER_LENGTH * gtime / MATCH_TIME;
				app.rect((PITCH_LENGTH - TIMER_LENGTH)/2, -54, d, 7);
				app.noFill();
				app.stroke(0);
				app.strokeWeight(1);
				app.rect((PITCH_LENGTH - TIMER_LENGTH)/2, -54, TIMER_LENGTH, 7);

				int mins = (int) (gtime / 60);
				float secs = gtime - 60 * mins;
				clockText = PApplet.nf(mins, 2) + ":" + PApplet.nf(secs,2,1);
			}
			else
				clockText = "GAME OVER";

			app.fill(0);
			app.text(clockText, (float) (PITCH_LENGTH - app.textWidth(clockText))/2, -26);

			app.popMatrix();
			app.popStyle();		

		}

	}

}
